package com.rc.mutievcharger.dto.ylevcharger.utils;

import com.rc.evcharger.common.base.yl.BaseYlCommand;
import com.rc.evcharger.common.code.YlControlCode;
import com.rc.evcharger.common.constant.WebConstant;
import com.rc.evcharger.common.redis.RedisDao;
import com.rc.evcharger.common.utils.DataUtil;
import com.rc.evcharger.common.utils.NumberUtil;
import com.rc.evcharger.common.utils.StringUtil;
import com.rc.mutievcharger.dto.ylevcharger.terminal.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;

/**
 * 主站响应或请求终端的消息
 *
 * @author yang
 */
public class YlMessageUtil {
    static Logger logger = LoggerFactory.getLogger(YlMessageUtil.class);

    public static final String START_SIGN = "AA F5";//帧起始符
    public static final String SPLIT = DataUtil.SPLIT;//分隔符
    public static final String NO_PASSWORD = "00";//分隔符

    public static final int START_SIGN_LENGTH = 2; //帧起始符长度
    public static final int DATA_LENGTH = 2;      //数据域长度
    public static final int CHECK_LENGTH = 1;     //校验码长度

    @Autowired
    public RedisDao redisDao;

    /**
     * 主站收到终端消息进行解码
     *
     * @param message
     * @return
     */
    public static YlTerminalMessage decoder(String message) {
        YlTerminalMessage terminalMessage = new YlTerminalMessage();
        String[] bcdCodes = message.split(DataUtil.SPLIT);
        List<YlTerminalMessage> result = new ArrayList<>();
        //StringBuffer sb = null;

        //int i1 = bcdCodes.length - 1;
        StringBuffer stringBuffer = new StringBuffer();

        if (!(bcdCodes[0] + DataUtil.SPLIT + bcdCodes[1]).equals(START_SIGN)) {
            logger.warn("异常起始报文:{}", message);
            return null;
        }

        //TODO 报文长度校验规则：起始域到校验和域整个报文长度
        int dataLength = Integer.parseInt(bcdCodes[3] + bcdCodes[2], 16);
        int resultLength = messageLengthCheck(bcdCodes.length, dataLength);
        if (resultLength != WebConstant.CON0) {
            logger.error("YL报文长度异常,报文长度不符:{}", message);
            return null;
        }


        for (int i = 0; i < bcdCodes.length; i++) {
            switch (i) {
                case 0:
                case 1:
                    terminalMessage.setStart_sign(bcdCodes[0] + DataUtil.SPLIT + bcdCodes[1]);
                    break;
                case 2:
                case 3:
                    terminalMessage.setLength(bcdCodes[2] + DataUtil.SPLIT + bcdCodes[3]);
                    break;
                case 4:
                    terminalMessage.setInfo(bcdCodes[i]);
                    break;
                case 5:
                    terminalMessage.setMsta(bcdCodes[i]);
                    break;
                case 6:
                case 7:
                    terminalMessage.setContral(bcdCodes[6] + DataUtil.SPLIT + bcdCodes[7]);
                    break;
                default:
                    //数据域
                    stringBuffer.append(bcdCodes[i] + SPLIT);
            }
        }

        //获取数据域和校验码
        String data = stringBuffer.toString().trim();
        terminalMessage.setData(data.substring(0, data.length() - 3));
        terminalMessage.setCs(data.substring(data.length() - 2));

        //todo 校验充电桩报文
        String crc = NumberUtil.checkNum(terminalMessage.getCheckBody().split(" "));//生成校验码
        if (crc.length() < 2) {
            crc = "0" + crc;
        }
        String cs = terminalMessage.getCs().toUpperCase();  //充电桩校验码

        //结算校验码默认为FF FF
        if (!crc.equals(cs)) {
            logger.error("YL报文校验失败,桩校验码:{},平台校验码:{},异常报文:{}", cs, crc, message);
            return null;
        }

        //获取桩逻辑地址
        switch (terminalMessage.getContral()) {
            case YlControlCode.LOGIN_6A:
            case YlControlCode.HEARTBEAT_MONITOR_66:
            case YlControlCode.ELEC_STATUS_68:
            case YlControlCode.ELEC_DATA_BALANCE_CA:
            case YlControlCode.RESP_CONTROL_CHARGE_START_STOP_08:
            case YlControlCode.RESP_EXCEPTON_WARN_6C:
                String terminalId = terminalMessage.getData().substring(4 * 3, 3 * (2 + 32) - 1);
                terminalMessage.setPileRtua(terminalId);    //桩逻辑地址
                terminalMessage.setTerminalId(StringUtil.resolveShTerminal(terminalId));
                break;
            default:
                //shTerminalMessage.setTerminalId(shTerminalMessage.getData().substring(0, 3 * 7 - 1));
        }

        return terminalMessage;
    }


    /**
     * 将数据变成帧格式
     *
     * @param message
     * @return
     */
    public static String createFrame(YlTerminalMessage message) {

        StringBuffer sb = new StringBuffer("");
        try {
            sb.append(START_SIGN).append(SPLIT).append(message.getLength()).append(SPLIT);
            sb.append(message.getInfo()).append(SPLIT).append(message.getMsta())
                    .append(SPLIT).append(message.getContral()).append(SPLIT);

            if (message.getData() != null && message.getData().length() > 0) {
                sb.append(message.getData()).append(SPLIT);
            }

            //获取校验码
            String crc = NumberUtil.checkNum(sb.toString().substring(3 * 6).split(SPLIT));
            sb.append(crc.length() == 1 ? "0" + crc : crc);
        } catch (Exception e) {
            logger.error("将数据变成帧格式帧message：" + message.getBody(), e);
        }
        return sb.toString();
    }

    /**
     * 公共构造响应帧
     *
     * @param message
     * @return
     */
    public static String getResponse(YlTerminalMessage message, String responseCode, BaseYlCommand baseCommand) {
        try {
            String dataAreaResp = "";
            if (baseCommand instanceof YlLoginCommondResp) {
                YlLoginCommondResp loginCommondResp = (YlLoginCommondResp) baseCommand;
                dataAreaResp = loginCommondResp.getObjectToString(true);
            } else if (baseCommand instanceof YlHearBeatCommondResp) {
                YlHearBeatCommondResp hearBeatCommondResp = (YlHearBeatCommondResp) baseCommand;
                dataAreaResp = hearBeatCommondResp.getObjectToString(true);
            } else if (baseCommand instanceof YlPriceRequestCommondResp) {
                YlPriceRequestCommondResp priceRequestCommondResp = (YlPriceRequestCommondResp) baseCommand;
                dataAreaResp = priceRequestCommondResp.getObjectToString(true);
            } else if (baseCommand instanceof YlStartCommandResp) {
                YlStartCommandResp startCommandResp = (YlStartCommandResp) baseCommand;
                dataAreaResp = startCommandResp.getObjectToString(true);
            } else if (baseCommand instanceof YlStopCommandResp) {
                YlStopCommandResp stopCommandResp = (YlStopCommandResp) baseCommand;
                dataAreaResp = stopCommandResp.getObjectToString(true);
            } else if (baseCommand instanceof YlChargingCommandResp) {
                YlChargingCommandResp chargingCommandResp = (YlChargingCommandResp) baseCommand;
                dataAreaResp = chargingCommandResp.getObjectToString(true);
            } else if (baseCommand instanceof YlTransactionsCommandResp) {
                YlTransactionsCommandResp transactionsCommandResp = (YlTransactionsCommandResp) baseCommand;
                dataAreaResp = transactionsCommandResp.getObjectToString(true);
            }
            //交易记录回复不带桩编号
//            String dataAreaResp;
//            if (baseCommand instanceof TransactionsCommandResp) {
//                dataAreaResp = loginCommondResp.getObjectToString(false);
//            } else {

//            }

            message.setData(dataAreaResp);

            message.setContral(responseCode);
            int areaLen = 0;
            if (message.getData().length() > 0) {
                areaLen = message.getData().split(SPLIT).length;
            }
            //其值为‘起始域到校验和’字节数之和  除数据域外，其他长度总和为9
            String hex = Integer.toHexString(areaLen + 9);
            if (hex.length() == 1) {
                hex = "0" + hex;
            }
            message.setLength(hex.toUpperCase() + DataUtil.SPLIT + "00");

        } catch (Exception e) {
            logger.error("公共构造响应帧message：" + message.getBody(), e);
        }
        return createFrame(message);
    }


    /**
     * 构造数据响应帧
     *
     * @param message
     * @return
     */
    public static String getResponseData(YlTerminalMessage message, String responseCode, boolean hasData) {
        try {
//            if (!hasData) {
//                message.setData("");
//            }
            message.setContral(responseCode);
            int len = 0;
            if (message.getData().length() > 0) {
                len = message.getData().split(SPLIT).length;
            }
            String hex = Integer.toHexString(len);
            if (hex.length() == 1) {
                hex = "0" + hex;
            }
            hex = hex.toUpperCase();
            String length = hex + SPLIT + "00";
            message.setLength(length);
        } catch (Exception e) {
            logger.error("公共构造响应帧message：" + message.getBody());
            logger.error("公共构造响应帧：" + e.toString());
        }
        return "";
        //return createFrame(message);
    }

    /**
     * 校验报文长度
     * 总长度-数据长度-帧头-长度码-校验码=0
     *
     * @param allLength  总长度
     * @param dateLength 数据长度
     * @return
     */
    static int messageLengthCheck(int allLength, int dateLength) {
        return allLength - dateLength;
    }


    public static void main(String[] args) throws Exception {
        String data = "68 8E 07 00 01 00 00 73 00 00 00 FC 16";
        String data1 = "68 19 00 51 05 02 00 68 8E 04 00 01 00 00 FF D3 16 68 19 00 51 05 02 00 68 81 2C 00 01 00 00 00 00 00 00 00 31 C8 20 17 04 14 09 55 37 00 88 C8 00 00 00 89 C8 04 02 00 04 C9 00 00 8D C8 00 00 00 00 8E C8 00 00 00 00 EB 16";
        String data2 = "68 19 00 71 01 02 00 68 81 2C 00 01 00 00 00 00 00 00 00 31 C8 20 17 06 01 15 43 37 00 88 C8 45 79 33 89 C8 61 49 07 04 C9 18 15 8D C8 00 00 00 00 8E C8 00 00 00 00 B9 16 68 19 00 71 01 02 00 68 A4 00 00 01 16 68 19 00 71 01 02 00 68 81 16 00 01 00 00 00 00 00 00 00 31 C8 20 17 06 01 15 43 37 00 40 C8 00 01 C4 16";
        String d = "68 19 00 51 12 02 00 68 8E 04 00 02 00 00 FF E1 16 68 19 00 51 12 02 00 68 8E 04 00 02 00 01 00 E3 16";
        String a = "68 88 88 88 88 02 00 68 81 0C 00 01 00 00 00 00 00 00 00 40 C8 01 01 85 16";
        //List<ZcTerminalMessage> list = ZcMessageUtil.decoder(a);
        //for (ZcTerminalMessage stm : list) {
        //    System.out.println(stm.getBody());
        //    System.out.println(stm.getContral());
        //    //Result result=new ElecControlResult("shenZhen");
        //    // ElecControlResult ecr= result.getResult(stm.getData());
        //    //System.out.println(ecr.getResult());
        //}

    }
}
